﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;

public class CheckUpdate : MonoBehaviour
{
    private string nativeVerPath;
    private string remoteVerText;
    public bool checkOver;
    public string strState;
    
    private List<string> needUpdate = new List<string>();
    Dictionary<string, string> remoteDic = new Dictionary<string, string>();
    Dictionary<string, string> nativeDic = new Dictionary<string, string>();
    Dictionary<string, string> packageDic = new Dictionary<string, string>();
    
    void Start()
    {
        DsLoader.GetSingleton();
        needUpdate.Clear();
        nativeDic.Clear();
        remoteDic.Clear();
        packageDic.Clear();

        nativeVerPath = Path.Combine(DsLoader.nativeUrl, "VersionNum.xml");
        Directory.CreateDirectory(DsLoader.nativeUrl);

        //读取本地版本号
        string nativeVerInfoPath = Path.Combine(DsLoader.nativeUrl, "VersionInfo.txt");
        FileStream inFile = new FileStream(nativeVerInfoPath, FileMode.OpenOrCreate);
        byte[] nativeVerInfoBytes = new byte[inFile.Length];
        inFile.Read(nativeVerInfoBytes, 0, (int)inFile.Length);
        inFile.Flush(); inFile.Close();

        int nativeVerInfo = 0;
        if (nativeVerInfoBytes.Length != 0)
        {
            string nativeVerInfoStr = Encoding.Default.GetString(nativeVerInfoBytes);
            nativeVerInfo = int.Parse(nativeVerInfoStr);
        }

        //读取包版本号
        string packageVerInfoStr = Resources.Load("VersionInfo").ToString();
        int packageVersion = int.Parse(packageVerInfoStr);

        //覆盖本地版本
        FileStream outFile = new FileStream(nativeVerInfoPath, FileMode.Create);
        byte[] packageVerInfoBytes = Encoding.Default.GetBytes(packageVerInfoStr);
        outFile.Write(packageVerInfoBytes, 0, packageVerInfoBytes.Length);
        outFile.Flush(); outFile.Close();

        //比较版本号，是否需要从包内更新
        if (nativeVerInfo < packageVersion)
        {
            //FileList记录的是包内所有AB文件，根据FileList就知道把哪些文件解压出去
            //TODO:此处考虑是否清空本地AB包，清空的话占用用户空间会减少，但是会消耗一定时间
            Object filelist = Resources.Load("AB/FileList");
            if (filelist != null)
            {
                XmlDocument fileListDoc = new XmlDocument();
                fileListDoc.LoadXml(filelist.ToString());
                XmlNode fileListRoot = fileListDoc.SelectSingleNode("FileList");
                foreach (XmlNode nativeNode in fileListRoot.ChildNodes)
                {
                    XmlElement xe = (XmlElement)nativeNode;
                    string path = xe.GetAttribute("FileName");
                    Object ab = Resources.Load(path);
                    strState = "正在解压文件:" + ab.name;
                    DsLoader.UnCompressRes(((TextAsset)ab).bytes, ab.name);
                }
            }
        }
        //checkOver = true;
        StartCoroutine("CheckForUpdate");
    }

    public IEnumerator CheckForUpdate()
    {
        //加载本地Version
        if (File.Exists(nativeVerPath))
        {
            XmlDocument nativeDoc = new XmlDocument();
            nativeDoc.Load(nativeVerPath);
            XmlNode nativeRoot = nativeDoc.SelectSingleNode("VersionNum");
            foreach (XmlNode nativeNode in nativeRoot.ChildNodes)
            {
                XmlElement xe = (XmlElement)nativeNode;
                nativeDic.Add(xe.GetAttribute("FileName"), xe.GetAttribute("Num"));
            }
        }
        strState = "读取本地Version完成";

        //下载远端Version
        WWW list = new WWW(GlobalString.REMOTE_URL + @"VersionNum.assetbundle");
        yield return list;
        if (list.error != null)
        {
            strState = "WWW error:" + list.error;
        }
        strState = "下载完成，没错误:";

        //加载远端Version
        TextAsset ts = list.assetBundle.mainAsset as TextAsset;
        remoteVerText = ts.text;
        strState = "读取远端xml完成";

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(ts.text);
        XmlNode root = doc.SelectSingleNode("VersionNum");
        foreach (XmlNode node in root.ChildNodes)
        {
            XmlElement xe = (XmlElement)node;
            remoteDic.Add(xe.GetAttribute("FileName"), xe.GetAttribute("Num"));
        }
        strState = "读取远端Version完成";

        //对比Version
        foreach (var pair in remoteDic)
        {
            if (!nativeDic.ContainsKey(pair.Key))
            {
                needUpdate.Add(pair.Key);
                continue;
            }

            int nativeVer = 0; int remoteVer = 0;
            int.TryParse(nativeDic[pair.Key], out nativeVer);
            int.TryParse(pair.Value, out remoteVer);
            if (nativeVer < remoteVer)
            {
                needUpdate.Add(pair.Key);
            }
        }
        strState = "对比Version完成";

        //更新本地Version
        FileStream stream = new FileStream(nativeVerPath, FileMode.Create);
        byte[] data = Encoding.UTF8.GetBytes(remoteVerText);
        stream.Write(data, 0, data.Length);
        stream.Flush(); stream.Close();

        strState = "文件已写入" + nativeVerPath;
        StartCoroutine("DownRes");
    }


    public IEnumerator DownRes()
    {
        foreach (string name in needUpdate)
        {
            string url = GlobalString.REMOTE_URL + UrlEncode(name);
            strState = "正在下载文件：" + name;
            WWW www = new WWW(url);
            yield return www;

            DsLoader.UnCompressRes(www.bytes, name);
            yield return new WaitForFixedUpdate();
        }
        checkOver = true;
    }

    public IEnumerator LoadRes(string name)
    {
        string nativeResPath = Path.Combine(DsLoader.nativeUrl, name);
        nativeResPath = "file://" + nativeResPath;
        strState = string.Format("Load Res:{0}", nativeResPath);
        WWW www = new WWW(nativeResPath);
        yield return www;

        AssetBundle bundle = www.assetBundle;
        Instantiate(bundle.mainAsset);
        bundle.Unload(false);
    }

    private string UrlEncode(string str)
    {
        StringBuilder sb = new StringBuilder();
        //默认是Encoding.Default.GetBytes(str)
        byte[] byStr = Encoding.UTF8.GetBytes(str);
        for (int i = 0; i < byStr.Length; i++)
        {
            sb.Append(@"%" + Convert.ToString(byStr[i], 16));
        }
        return (sb.ToString());
    }

    void Update()
    {
        if (checkOver)
        {
            DsLoader.GetSingleton().InitResJson();
            SceneManager.LoadScene("TestLoad");
        }
    }

    public void OnGUI()
    {
        GUI.Label(new Rect(10, 10, 800, 20), strState);
    }
}